home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Programming / ARexxGuide / Editors / ARx_Help.ttx < prev    next >
Text File  |  1994-03-30  |  19KB  |  513 lines

  1. /** $VER: ARx_Help.TTX 2.0a (28 Feb 1994,30 Mar 1994)
  2.  ** by Robin Evans
  3.  **
  4.  ** Display the ARexxGuide page for the word currently under the
  5.  ** cursor. Will call ARx_Setup.rexx if env: variables are not set.
  6.  **
  7.  ** Add the following line to your TTX_Startup.dfn file, in the KEYBOARD:
  8.  ** section.
  9.  **
  10.  **     HELP               ExecARexxMacro "ARx_Help"
  11.  **
  12.  ** See `Tutorials: Help key macros' in ARexxGuide for more information
  13.  ** about this macro.
  14.  **/
  15.  
  16. signal on syntax
  17. signal on break_c
  18. signal on halt
  19. signal on failure
  20.  
  21. options results
  22. parse arg LkUp
  23.  
  24. call addlib('rexxsupport.library',0,-30)
  25. call addlib('amigaguide.library',-1,-30)
  26.  
  27. TRUE=1; FALSE=0
  28.  
  29.    /* Load the cross-ref file. Function returns quickly if the file is  **
  30.    ** already loaded, but -- like ADDLIB() it can return true even if   **
  31.    ** the file isn't available, so we check by looking for a known node.*/
  32. call DisplayStatus('ARx_Help: Checking .xref files...')
  33. do Attempt = 1
  34.     call LoadXref('ARx_Guide.xref')
  35.    if getxref('TRACEOPT1') = 10 then do   /* Leave below */
  36.       /* Did this in a loop just to be able to use signal for a no-load */
  37.       if Attempt = 2 then
  38.           signal XRefError
  39.       else if 'ARx_Setup.rexx'('HELP',,address()) ~= 0 then signal XRefError
  40.    end
  41.    else leave Attempt
  42. end
  43.  
  44. /* Add any extra files included in the env: variable.                */
  45. ExtraXRef = GetEnv('ARexxGuide/XRFiles')
  46. do i = 1 for words(ExtraXRef)
  47.       /* 'Call' because we don't care about errors here.             */
  48.    call loadxref(word(ExtraXRef, i))
  49. end
  50.  
  51. call DisplayStatus('ARexxGuide online help system...')
  52.  
  53.    /* It isn't used in the setup provided here, but it's possible to    **
  54.    ** just pass a word as an argument to this routine and get a lookup  **
  55.    ** on that.                                                          */
  56. if LkUp = '' then do
  57.       /* Get the current line and position. Editor's commands are all   **
  58.       ** in subroutines and not in the main code.                       */
  59.    HLine = GetCLine()
  60.    CurPos = GetCurPos()
  61.       /* Show the index requester if it's a blank line */
  62.    if HLine = '' | verify(HLine, ' ;') = 0 then do
  63.       call ShowInfo(,, CurPos, Kwd)
  64.       signal CleanExit
  65.    end
  66.  
  67.       /* Cut a single clause out of preceding clauses                   */
  68.    SemPos = lastpos(';', HLine, CurPos) + 1
  69.       /* This will break if a semicolon is used within a string         **
  70.       ** but checking for that seems like overkill.                     */
  71.    if SemPos > 1 then do
  72.       if SemPos < CurPos + 1 then do
  73.          parse var HLine =SemPos HLine ';'
  74.          CurPos = CurPos - SemPos + 1
  75.       end
  76.    end
  77.       /* Cut it out of following clauses                                 */
  78.    else
  79.       parse var HLine HLine ';'
  80.  
  81.    /* The current keyword is used within MChar select clause             */
  82.    Kwd = upper(word(HLine, 1))
  83.  
  84.                                               /* Hex characters: SpTbRt    */
  85.       /* Check for special characters -- operators, quotation marks, etc */
  86.    MChar = pos(substr(HLine,CurPos,1), '+-/*%|&^><=,;:~)("''?!.'||'20090a'x)
  87.    select
  88.       when MChar = 0 then do     /* It isn't one of the chars */
  89.          /* Look for whole word if it isn't a special character */
  90.          LkUp = GetCWord(HLine, CurPos)
  91.       end
  92.       when MChar <= 5 then
  93.          select
  94.             when MChar <= 2 then       /* + or - */
  95.                if Kwd = 'PARSE' then
  96.                   LkUp = 'PARSETMP5'
  97.                else
  98.                   LkUp = 'ARITHMETIC'
  99.             when MChar <= 4 then do    /* / or * */
  100.                   /* This picks up the three characters surrounding a '*' or '/' */
  101.                ComChar = substr(HLine, max(1, CurPos - 1), 3)
  102.                if pos('/*', ComChar) + pos('*/', ComChar) > 0 then
  103.                   LkUp = 'COMMENT'
  104.                else
  105.                   LkUp = 'ARITHMETIC'
  106.             end
  107.             otherwise
  108.                 LkUp = 'ARITHMETIC'        /* % */
  109.          end
  110.       when MChar <= 13 then
  111.          select
  112.             when MChar <= 8 then do    /* | or & or ^ */
  113.                   /* This picks up the three characters surrounding token */
  114.                ComChar = substr(HLine, max(1, CurPos - 1), 3)
  115.                if pos('||', ComChar) > 0 then
  116.                   LkUp = 'CONCATENATION'
  117.                else
  118.                   LkUp = 'LOGICAL'
  119.             end
  120.             when MChar <= 10 then    /* < or > */
  121.                LkUp = 'COMPARISON'
  122.             when MChar = 11 then    /* = */
  123.                if Kwd = 'PARSE' then
  124.                   LkUp = 'PARSETMP5'
  125.                else if symbol(strip(left(HLine, max(1, CurPos-1)))) == 'BAD' then
  126.                   LkUp = 'COMPARISON'
  127.                else
  128.                   LkUp = 'ASSIGNMENT'
  129.             when MChar = 12 then    /* , */
  130.                LkUp = 'COMMA'
  131.             otherwise               /* ; */
  132.                LkUp = 'SEMICOLON'
  133.          end
  134.       when MChar <= 19 then
  135.          select
  136.             when MChar = 14 then    /* : */
  137.                LkUp = 'LABEL'
  138.             when MChar = 15 then do /* ~ */
  139.                   /* is the next character a comparison operator? */
  140.                if pos(substr(HLine, CurPos , 2), '~=~>~<') > 0 then
  141.                   LkUp = 'COMPARISON'
  142.                else
  143.                   LkUp = 'LOGICAL'
  144.             end
  145.             when MChar <=17 then    /* ) or ( */
  146.                if Kwd = 'PARSE' then
  147.                   LkUp = 'PARSETMP5'
  148.                else
  149.                   LkUp = 'PAREN'
  150.             otherwise               /* " or ' */
  151.                LkUp = 'STRING'
  152.          end
  153.       otherwise
  154.          select
  155.             when MChar = 20 then    /* ? */
  156.                if Kwd = 'TRACE' then
  157.                   LkUp = 'TRACEOPT1'
  158.                else
  159.                   LkUp = '?'
  160.             when MChar = 21 then    /* ! */
  161.                if Kwd = 'TRACE' then
  162.                   LkUp = 'TRACEOPT2'
  163.                else
  164.                   LkUp = '!'
  165.             when MChar = 22 then do   /* . -- dot  */
  166.                   /* Get the surrounding ARexx token */
  167.                StPos = verify(' 'HLine, '+-|/&=~\><^,;:()"'' ', 'M', lastpos(' ', ' 'HLine, CurPos))
  168.                Token = substr(HLine, StPos, verify(HLine' ', '+-|/&=~\><^,;:()"'' ', M, CurPos) - StPos)
  169.                select
  170.                    when Token = '.' then
  171.                       if Kwd = 'PARSE' then
  172.                          LkUp = 'PARSETMP2'
  173.                       else
  174.                          LkUp = Token
  175.                    when datatype(Token, 'N') then
  176.                        LkUp = 'NUMBER'
  177.                    when datatype(Token, 'S') then
  178.                        if datatype(left(Token,1),'M') | verify(Token, '!@#$', 'M') = 1
  179.                            then LkUp = 'COMPVAR'
  180.                    otherwise
  181.                       LkUp = Token
  182.                 end
  183.             end
  184.             otherwise               /* At a space or EOL */
  185.                if CurPos >= wordindex(HLine, 1) then
  186.                   LkUp = GetCWord(HLine, CurPos)
  187.                else do
  188.                   call ShowInfo(HLine,, CurPos, Kwd)
  189.                   signal CleanExit
  190.                end
  191.          end
  192.    end
  193.  
  194.  
  195.    /* Check for special words like `command' in `address command'       **
  196.    ** and most of the subkeywords in instructions like DO.              */
  197.    if word(HLine, 1) ~= LkUp then do CheckOpt = 1 for 1  /* Let's us leave */
  198.       if GetXRef(LkUp) = 10 | find('ARG PULL UPPER COMMAND', upper(LkUp)) > 0 then do
  199.          if word(GetXRef(Kwd),3) = 2 then select
  200.             when Kwd = 'DO' then do
  201.                SpecWord = find('UNTIL WHILE TO FOR BY FOREVER ', upper(LkUp))
  202.                if SpecWord > 0 then
  203.                   LkUp = word('DOOPT4 DOOPT4 DOOPT2 DOOPT3 DOOPT2 DOOPT5', SpecWord)
  204.             end
  205.             when Kwd = 'PARSE' then do
  206.                SpecWord = find('ARG PULL EXTERNAL NUMERIC SOURCE VERSION VALUE VAR WITH', upper(LkUp))
  207.                if SpecWord > 0 then do
  208.                   LkUp = 'PARSESRC'SpecWord
  209.                   if SpecWord = 9 then
  210.                      LkUp = 'PARSESRC7'
  211.                end
  212.                else
  213.                   LkUp = 'PARSETMP1'
  214.             end
  215.             when Kwd = 'OPTIONS' then
  216.                if find('RESULTS PROMPT FAILAT CASHE ON OFF', upper(LkUp)) > 0 then
  217.                   LkUp = Kwd
  218.             when Kwd = 'TRACE' then
  219.                if verify(upper(right(LkUp,1)), 'IRACLENOBS') = 0 then
  220.                   LkUp = 'TRACEOPT'
  221.             when Kwd = 'SIGNAL' then
  222.                if find('ON OFF', upper(LkUp)) >0 then
  223.                   LkUp = 'SIGTRAP'
  224.                else if pos('BREAK_', upper(LkUp)) = 1 then
  225.                   LkUp = 'BREAK_'
  226.                else
  227.                   LkUp = 'SIGTRAN'
  228.             when upper(LkUp) = 'UPPER' then
  229.                if Kwd ~= 'UPPER' then
  230.                   LkUp = 'UPPER()'
  231.             when Kwd = 'ADDRESS' then
  232.                if abbrev(word(HLine, 2), LkUp) then do
  233.                   LkUp = Kwd
  234.                   leave CheckOpt  /* so we don't get address() */
  235.                end
  236.             otherwise
  237.          end
  238.          if GetXRef(LkUp'()') ~= 10 then
  239.             LkUp = LkUp'()'
  240.       end
  241.    end
  242. end
  243. else do     /* Word was supplied as argument to the script */
  244.    upper LkUp
  245.    CurPos = 1; HLine = LkUp
  246. end
  247.  
  248. XRVal = upper(GetXRef(LkUp))
  249. if find('10 NODE/K', XRVal) > 0 then do
  250.    if ShowInfo( HLine, LkUp, CurPos, Kwd ) = 0 then signal CleanExit
  251.     else XRVal = upper(GetXRef(LkUp))
  252. end
  253.  
  254. if ~abbrev(word(XRVal,2), '"ARX_') then
  255.    Src = 'Other ref:'
  256. else
  257.    Src = 'ARexxGuide:'
  258. call DisplayStatus(Src upper(LkUp) '['word('Explanation Function Instruction', word(getxref(LkUp), 3)+1)']')
  259.  
  260. signal on error
  261. call DisplayAG(LkUp)
  262. signal off error
  263.  
  264. CleanExit:
  265.     /* Since it can cause severe problems, it's removed when not needed */
  266. call remlib('amigaguide.library')
  267. call EditorExit()
  268. exit 0
  269.  
  270. /*************************************************************************
  271. ** Error routines.                                                      */
  272.  
  273. XRefError:
  274.    ErrMsg = 'Unable to load the cross-reference file ARx_Guide.xref\'
  275.    if ~exists('env:amigaguide/path') then
  276.       ErrMsg = ErrMsg || 'Your environmental variable "amigaguide/path" is not set.\'
  277.    else
  278.       ErrMsg = ErrMsg '  Be sure to include that file''s directory in env:amigaguide/path.\'
  279.    ErrMsg = ErrMsg '  The .xref file may be put into the current directory or into\',
  280.    '  any directory included in the amigaguide/path environmental variable.'
  281.    call PutErrMsg(SIGL, ErrMsg)
  282.    exit 6
  283. NoCmd:
  284.    call PutErrMsg(SIGL, 'Can''t read environmental variable "env:arexxguide/AGcmd".\',
  285.              '  That variable must hold the name of the command you use\',
  286.              '  to show AmigaGuide files.')
  287.    exit 7
  288. Syntax:
  289.    call PutErrMsg(SIGL, '   Syntax error #'rc ':' errortext(rc))
  290.    exit 9
  291. Failure:
  292.    call PutErrMsg(SIGL, '   Command "'sourceline(SIGL)'" failed.')
  293.     exit 10
  294. Halt:
  295. Break_C:
  296.    call PutErrMsg(SIGL, '   Execution halted.')
  297.     exit 8
  298. Error:
  299.    call PutErrMsg(SIGL, '   Command error in display routine: RC =' rc'.\\',
  300.              '  The name of your AmigaGuide viewer may not be properly set, or\',
  301.              '  an .xref file might have been loaded for a database not located\',
  302.              '  in one of the directories in env:AmigaGuide/path.\',
  303.              '  Type rx ARx_Setup at a shell prompt to run the setup program again.')
  304.     exit 9
  305. PutErrMsg:
  306.    call trace b
  307.    ErrMsg ='Sorry an enexpected error has occurred in line' arg(1)'.\\'arg(2)
  308.    signal off syntax
  309.    signal off halt
  310.    signal off break_c
  311.    WinHi = 59 + CountChar('\', ErrMsg) * 11
  312.    call DisplayStatus('ARx_Help macro error.')
  313.    if open(6ErrWin, 'raw:0/0/640/'WinHi'/Arx_Help Error/SCREEN *') then do
  314.       call writeln(6ErrWin, translate(ErrMsg,'0a'x, '\'))
  315.       call writech(6ErrWin, '0a'x'        -- Press any key -- ')
  316.       call readch(6ErrWin)
  317.    end
  318.    call EditorExit()
  319.    return 0
  320.  
  321. exit 0
  322.  
  323. /*************************************************************************
  324. ** General utility routines                                             */
  325.  
  326. GetAGCmd: procedure
  327.         /* Calls the setup program if env:ARexxGuide/AGCmd is not set       */
  328.     AGCmd = GetEnv('ARexxGuide/AGCmd')
  329.    if AGCmd = '' then do
  330.        call DisplayStatus('Please wait... Running setup routine')
  331.       if 'ARx_Setup.rexx'('HELP',,address()) ~= 0 then
  332.          signal NoCmd
  333.         else
  334.             AGCmd = GetEnv('ARexxGuide/AGCmd')
  335.     end
  336.     return AGCmd
  337.  
  338. ShowInfo:
  339.       /* The env: var ShowFullHelp determines whether a simple editor     **
  340.       ** requester is used, or a complex rexxarplib window that displays  **
  341.       ** far more information about the current line, but is also slow.   */
  342.    if getenv('ARexxGuide/ShowFullHelp') ~= '1' then do
  343.       if BoolReq(upper(LkUp) 'not found.','Show ARexxGuide index?') then do
  344.          LkUp = 'ARx_NdxCont'
  345.          return 1
  346.       end
  347.       else
  348.           return 0
  349.    end
  350.    else do
  351.          /* Show that we're doing something */
  352.       call DisplayStatus(LkUp 'not found. Checking clause...')
  353.  
  354.          /* The .rexx part of the name has to be added because the default **
  355.          ** extension is set by editor: .TTX, .edge, etc. Since this       **
  356.          ** is set up for different editors, it's stored with the generic  **
  357.          ** extension.                                                     */
  358.       return 'ARx_RArpInfoWin.rexx'(HLine,LkUp,CurPos,Kwd,SetAddress(),SetExecStr(),GetWinInfo())
  359.    end
  360.  
  361. CountChar:
  362.    return length(arg(2)) - length(compress(arg(2), arg(1)))
  363.  
  364. GetEnv: procedure
  365.       /* Arguments:                                                     **
  366.       **   arg(1) := The name of the variable to retrieve               **
  367.       ** Returns     a string                                           */
  368.  
  369.         /* Use external function of same name if it's available           */
  370.     if show('L', 'rexxarplib.library') then
  371.         return 'GetEnv'(arg(1))
  372.       /*  OPEN()  will fail if variable is not defined. Null will be    **
  373.       ** returned in that case                                          */
  374.    if open(6Env, 'env:'arg(1), 'R') then do
  375.       EnvVar = readln(6Env)
  376.       call close 6Env
  377.    end
  378.    else EnvVar = ''
  379.    return EnvVar
  380.  
  381. Tab2Space:  procedure
  382.    parse arg TSize, Line
  383.    tpos=pos('09'x,Line);
  384.    do while tpos>0;
  385.       Line=insert('',Line, tpos, min(1, tpos//TSize)*(TSize-tpos//TSize));
  386.       tpos=pos('09'x, Line,tpos+1);
  387.    end;
  388. return translate(Line,' ','09'x)
  389.  
  390.  
  391. /***********************************************************************
  392. ** Editor-specific commands.                                          **
  393. **    These function calls are used elsewhere to make it easier to    **
  394. **    use the same script for different editors.                      **
  395. **                                                                    **
  396. ** For help in customizing the macro for a different editor see       **
  397. ** ARexxGuide Tutorials section: Building a help macro                */
  398.  
  399. GetCLine: procedure
  400.    'SetInputLock on'
  401.    'GetPrefs tabwidth'
  402.    TabSize = result
  403.    'GetLine 1'
  404.    return Tab2Space(TabSize,result)
  405.  
  406. GetCurPos: procedure
  407.    'GetCursorPos'
  408.    CurPos = word(result, 2)
  409.    'SetInputLock off'
  410.    return CurPos
  411.  
  412. GetCWord: procedure
  413.       /* Send back current word */
  414.    'GetWord'
  415.    return result
  416.  
  417.       /* Use default version for testing */
  418.    parse arg Line, CPos
  419.       /* list of valid word-separator charaters: space, operator, spec char */
  420.    SepChar = ' +-*/%|&~=><^,;:()."''\'
  421.       /* Back up in line if Current position is not an alpha character  or digit */
  422.    do while (verify(substr(Line,CPos,1), SepChar || '0a'x)=0) & (CPos>1)
  423.       CPos = CPos - 1
  424.    end
  425.       /* Cut off word at space _or_ any of the operator or special characters     */
  426.    say Line
  427.    Word = reverse(left(Line,verify(Line' ',SepChar,'M',CPos) - 1))
  428.    return reverse(left(Word,verify(Word' ',SepChar,'M', max(1,length(Word) + 1 - CPos))-1))
  429.       /* Send back current word */
  430.  
  431. DisplayStatus:
  432.       /* Put message in title bar of editor */
  433.    'SetStatusBar' arg(1)
  434.    return 0
  435.  
  436. BoolReq:
  437.       /* Present a Yes/No requester                                      **
  438.       ** Arguments:                                                      **
  439.       **    arg(1)   := Titlebar text                                    **
  440.       **    arg(2)   := Message in body of requester                     */
  441.    if show('L', 'rexxreqtools.library') then
  442.       return rtezrequest(arg(2), '_Yes|_No', arg(1))
  443.    'RequestBool "'center(arg(1),37)'" "'center(arg(2),37)'"'
  444.       /* return a Boolean value                                          */
  445.    return ( result = 'YES' )
  446.  
  447. GetWinInfo:
  448.       /* Return Information about window                                 **
  449.       **    Format of returned value:                                    **
  450.       **           word 1 = x position                                   **
  451.       **           word 2 - y position                                   **
  452.       **           word 3 = name of public screen                        */
  453.   'GetScreenInfo'
  454.    PubScreen = word(result, words(result))
  455.    'GetWindowInfo'
  456.    return word(result,2) word(result,3) PubScreen
  457.  
  458. EditorExit:
  459.       /* Used for any editor-specific commands that should be issued on  **
  460.       ** exit.                                                           */
  461.    'SetInputLock off'
  462.    'SetDisplayLock off'
  463. /* 'SetStatusBar'  */
  464.    return 0
  465.  
  466. SetExecStr:
  467.       /* The string returned by this function is used in the rexxarplib  **
  468.       ** window to send link commands to AmigaGuide.                     */
  469.    AGCmd = GetAGCmd()
  470.    if ~abbrev(AGCmd, 'Multi') then
  471.       return 'ExecARexxString address ARX_ARP quit; if ~show(P, ARX_GUIDE) then do;address command; ''run' AGCmd 'ARexxGuide.guide portname ARX_GUIDE'';waitforport ARX_GUIDE; end; address ARX_GUIDE; windowtofront; link '
  472.    else
  473.       return 'ExecARexxString address ARX_ARP quit; address command; ''run' AGCmd 'document'
  474.  
  475. SetAddress:
  476.       /* Address used as target of the commands from rarp window         */
  477.    return address()
  478.  
  479. DisplayAG:
  480.       /* Show the node in AmigaGuide viewer. Missing env: will call      **
  481.       ** error handler which runs the setup prg. and then passes         **
  482.       ** control back to here.                                           */
  483.    arg LkUp
  484.    AGCmd = GetAGCmd()
  485.  
  486.    if abbrev(AGCmd, 'Multi') then
  487.       PrtOpt = ''
  488.    else
  489.       PrtOpt = 'portname ARX_GUIDE'
  490.       /* See if our AG window is open */
  491.    if ~show('P','ARX_GUIDE') then do
  492.       if pos('/', LkUp) > 0 then
  493.          parse var LkUp DB '/' Doc
  494.       else
  495.          DB = ''
  496.       address command  'run' AGCmd DB 'document' LkUp PrtOpt 'pubscreen' word(getwininfo(), 3) 'requester'
  497.    end
  498.    else do
  499.          /* show the node */
  500.       address ARX_GUIDE
  501.       'Link' LkUp
  502.       'unzoomwindow'
  503.       'windowtofront'
  504.       address
  505.          /* This will be called only if rexxarplib is available and will **
  506.          ** try to bring a public screen to the foreground. OK if there  **
  507.          ** isn't a screen of that name available.                       */
  508.       if show('L', 'rexxarplib.library') then
  509.          call screentofront('ARX_GUIDE')
  510.    end
  511.  
  512. return 0
  513.